#include "stdafx.h"
#include "domnodebuilder.h"

#include <data/map/ieditableglobalmap.hpp>
#include <data/map/ieditablecell.hpp>
#include <data/map/ieditabletile.hpp>

#include <QtCore/QTextStream>
#include <QtCore/QStringList>
#include <QtCore/QFile>

// FIXME: syncronize this constant with <demo/tile.h>
static const uint EDGES_COUNT = 4;

const char C_NODE_MAP[] = "map";
const char C_NODE_CELL_ROOT[] = "cells";
const char C_NODE_CELL[] = "cell";

namespace Demo {

static inline
void buildTileNode(const Data::ITile &tile,
                   QDomElement &target)
{
    target.setAttribute("ground_variant", tile.ground());

    QString nodeValue;
    nodeValue.reserve(10 * Data::ITile::KEYPOINTS_COUNT);
    for (uint index = 0; index < Data::ITile::KEYPOINTS_COUNT; ++index) {
        nodeValue += QString::number(tile.keyPoint(index), 'g', 2);
        nodeValue += ";";
    }
    target.setAttribute("edges", nodeValue);
}

static inline
void parseEdgesInfo(const QString &edges, Data::IEditableTile &tile)
{
    QStringList list = edges.split(QLatin1Char(';'));
    int limit = qMin<int>(list.size(), Data::ITile::KEYPOINTS_COUNT);
    for (int index = 0; index < limit; ++index) {
        double height = list[index].toDouble();
        tile.setKeyPoint(index, height);
    }
}

////////////////////////////////////////////////////////////////////////////////
// class implementation

void DomNodeBuilder::buildDocument(const Data::IGlobalMap &map,
                                   QDomDocument &document)
{
    QDomElement mapNode = document.createElement("map");
    mapNode.setAttribute("width", map.width());
    mapNode.setAttribute("height", map.height());
    // writing texture names
//    {
//        const auto &ref = map.getTextureGroup();
//        QDomElement textures = document.createElement("textures");
//        QDomElement surface;
//        for (uint index = 0; index < ref.size(); ++index) {
//            QString path = QString::fromStdString(ref.texture(index).name());
//            surface = document.createElement("surface");
//            surface.setAttribute("path", path);
//            textures.appendChild(surface);
//        }
//        mapNode.appendChild(textures);
//    }
    // writing tiles info
    {
        QDomElement cells = document.createElement("cells");
        QDomElement cell;
        for (uint y = 0; y < map.height(); ++y)
            for (uint x = 0; x < map.width(); ++x) {
                cell = document.createElement(C_NODE_CELL);
                buildTileNode(map.cell(x, y).tile(), cell);
                cells.appendChild(cell);
            }
        mapNode.appendChild(cells);
    }
    document.appendChild(mapNode);
}

void DomNodeBuilder::readDocument(const QString &path, QDomDocument &document)
{
    QFile file(path);
    if (file.open(QIODevice::ReadOnly)) {
        document.setContent(&file);
    } else {
        myDebug() << "Cannot read map: file doesn't exist.\n";
    }
}

void DomNodeBuilder::writeDocument(const QDomDocument &document,
                                   const QString &path)
{
    QFile file(path);
    if (file.open(QIODevice::WriteOnly)) {
        QTextStream stream(&file);
        stream << document.toString(2);
    }
}

void DomNodeBuilder::buildMap(const QDomDocument &document,
                              Data::IEditableGlobalMap &map)
{

    QDomElement root = document.firstChildElement(C_NODE_MAP);
    if (root.isNull())
        return;
    QString sWidth = root.attribute("width");
    QString sHeight = root.attribute("height");
    uint width = sWidth.isEmpty() ? 10 : sWidth.toUInt();
    uint height = sHeight.isEmpty() ? 10 : sHeight.toUInt();

    map.create(width, height);

//    {
//        QDomElement textures = root.firstChildElement("textures");
//        auto &target = map.getTextureGroup();
//        QDomElement surface = textures.firstChildElement("surface");
//        while (!surface.isNull()) {
//            std::string path = surface.attribute("path").toStdString();
//            target.load(path);
//            surface = surface.nextSiblingElement("surface");
//        }
//    }
    {
        QDomElement cells = root.firstChildElement("cells");
        uint x = 0;
        uint y = 0;
        QDomElement cell = cells.firstChildElement(C_NODE_CELL);
        while (!cell.isNull()) {
            uint variant = cell.attribute("ground_variant", "0").toUInt();
            auto &iTile = map.editableCell(x, y).editableTile();
            iTile.setGround(variant);
            parseEdgesInfo(cell.attribute("edges"), iTile);

            ++x;
            if (x >= map.width()) {
                x = 0;
                ++y;
            }
            cell = cell.nextSiblingElement(C_NODE_CELL);
        }
    }
}

} // namespace Demo
